package com.flying.invest.invest.service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

import com.flying.common.annotation.DaoCreate;
import com.flying.common.annotation.DaoQuery;
import com.flying.common.annotation.DaoRemove;
import com.flying.common.annotation.DaoUpdate;
import com.flying.common.annotation.Transaction;
import com.flying.common.util.Codes;
import com.flying.common.util.Utils;
import com.flying.framework.annotation.MethodInfo;
import com.flying.framework.annotation.Param;
import com.flying.framework.annotation.Service;
import com.flying.framework.annotation.event.MethodListener;
import com.flying.framework.annotation.event.MethodListenerHandler;
import com.flying.framework.context.ServiceContext;
import com.flying.framework.exception.AppException;
import com.flying.framework.model.ActionResult;
import com.flying.framework.model.ModelFactory;
import com.flying.framework.model.QueryResult;
import com.flying.framework.security.Principal;
import com.flying.framework.service.AbstractService;
import com.flying.invest.assets.model.Assets;
import com.flying.invest.assets.service.AssetsPriceService;
import com.flying.invest.assets.service.AssetsService;
import com.flying.invest.invest.TransactionType;
import com.flying.invest.invest.model.Investment;
import com.flying.invest.invest.model.Investment.Status;
import com.flying.invest.invest.model.Investment.SurveyStatus;
import com.flying.invest.invest.model.InvestmentProxy;
import com.flying.invest.invest.model.InvestmentTransaction;
import com.flying.invest.strategy.model.Strategy;
import com.flying.invest.strategy.service.StrategyService;

@Service(value="InvestmentService", desc="")
public class InvestmentService extends AbstractService{
	private AssetsService as;
	private AssetsPriceService aps;
	private StrategyService strategyService;
	private InvestmentTransactionService transactionService;
	private InvestmentSuggestionService suggestionService;
	
	public void setAssetsService(AssetsService s) {
		this.as = s;
	}
	public void setAssetsPriceService(AssetsPriceService s) {
		this.aps = s;
	}
	public void setInvestmentTransactionService(InvestmentTransactionService s) {
		this.transactionService = s;
	}
	public void setStrategyService(StrategyService s) {
		this.strategyService = s;
	}
	public void setInvestmentSuggestionService(InvestmentSuggestionService s) {
		this.suggestionService = s;
	}
        
	@MethodInfo("新增")
	@DaoCreate(entity=Investment.ENTITY_NAME)
	public Investment create(
		
			@Param(value=Investment.ASSETS_ID, required=true,	desc="投资品种") Long assets_id,
			@Param(value=Investment.ACCOUNT_ID, required=true,	desc="投资账户ID") Long account_id,
			@Param(value=Investment.SURVEY_ID, required=false,	desc="调查ID") Long survey_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, max="8") Integer status,
			@Param(value=Investment.PLAN_START, required=false,	desc="计划开始") Date plan_start,
			@Param(value=Investment.PLAN_END, required=false,	desc="计划结束") Date plan_end,
			@Param(value=Investment.PLAN_MONEY, required=false,	desc="计划投入金额") Double plan_money,
			@Param(value=Investment.LIMIT_RATE, required=false,	desc="限制比例") Double limitRate,
			@Param(value=Investment.ACTUAL_START, required=false,	desc="实际开始") Date actual_start,
			@Param(value=Investment.CODE, required=false,	desc="代码") String code,
			@Param(value=Investment.NAME, required=false,	desc="名称") String name,
			@Param(value=Investment.REMARKS, required=false,	desc="说明") String remarks,

			@Param(value=Investment.MARKET_INFO, required=false,	desc="大盘判断") String market_info,
			@Param(value=Investment.ASSETS_INFO, required=false,	desc="入市时机") String assets_info,
			@Param(value=Investment.BUY_INFO, required=false,	desc="建仓计划") String buy_info,
			@Param(value=Investment.SELL_INFO, required=false,	desc="出仓标准") String sell_info,
			
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Investment.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value=Investment.PRICE, required=false,	desc="价格") Double price,
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.CREATOR, required=false,	desc="创建人") String creator,
			@Param(value=Investment.CREATE_TIME, required=false,	desc="创建时间") Date create_time
		
		) throws Exception {
		Principal p = ServiceContext.getContext().getPrincipal();
		Assets assets = this.as.findById(assets_id);
		if(price == null) {
			price = assets.getPrice();
		}
//		if(code == null) {
//			code = assets.getCode()+"."+DateUtils.formatDate(new Date(), "yyyyMMdd");
//		}
		return ModelFactory.create(Investment.class, 
				Investment.STATUS, status == null? Status.PREPARING.value: status,
				Investment.SURVEY_STATUS, survey_id == null?SurveyStatus.NONE.value: SurveyStatus.CREATED.value,
				Investment.CURRENCY, currency == null?assets.getCurrency(): currency,
				Investment.PRICE, price,
				Investment.NAME, name == null?assets.getName(): name,
				Investment.CODE, code,
				Investment.USER_ID, Long.parseLong(p.getId()),
				Investment.PRICE, price == null?0.0: price,
				Investment.CREATOR, (p == null?null: p.getName()),
				Investment.CREATE_TIME, new Date());
	}

	@MethodInfo("修改")
	@MethodListener(handlers={@MethodListenerHandler(serviceId="InvestmentService:updateIncludeStrategies")})
	@Transaction
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	public ActionResult update(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.ASSETS_ID, required=true,	desc="投资品种") Long assets_id,
			@Param(value=Investment.ACCOUNT_ID, required=true,	desc="投资账户ID") Long account_id,
			@Param(value=Investment.SURVEY_ID, required=false,	desc="调查ID") Long survey_id,
			@Param(value=Investment.STATUS, required=true,	desc="状态", enumClass=Status.class) Integer status,
			@Param(value=Investment.PLAN_START, required=false,	desc="计划开始") Date plan_start,
			@Param(value=Investment.PLAN_END, required=false,	desc="计划结束") Date plan_end,
			@Param(value=Investment.PLAN_MONEY, required=false,	desc="计划投入金额") Double plan_money,
			@Param(value=Investment.LIMIT_RATE, required=false,	desc="限制比例") Double limitRate,
			@Param(value=Investment.ACTUAL_START, required=false,	desc="实际开始") Date actual_start,
			@Param(value=Investment.ACTUAL_END, required=false,	desc="实际结束") Date actual_end,
			@Param(value=Investment.CODE, required=false,	desc="代码") String code,
			@Param(value=Investment.NAME, required=false,	desc="名称") String name,
			@Param(value=Investment.REMARKS, required=false,	desc="说明") String remarks,

			@Param(value=Investment.MARKET_INFO, required=false,	desc="大盘判断") String market_info,
			@Param(value=Investment.ASSETS_INFO, required=false,	desc="入市时机") String assets_info,
			@Param(value=Investment.BUY_INFO, required=false,	desc="建仓计划") String buy_info,
			@Param(value=Investment.SELL_INFO, required=false,	desc="出仓标准") String sell_info,

			@Param(value=Investment.CURRENCY, required=false,	desc="币种") String currency,
			@Param(value=Investment.UPDATOR, required=false,	desc="修改人") String updator,
			@Param(value=Investment.UPDATE_TIME, required=false,	desc="修改时间") Date update_time
			
		) throws Exception {
		Investment v = this.findById(invest_id);
		if(v.getStatus() == Status.FINISHED.value()) {
			throw new AppException("0101", v.getName()+"["+v.getCode()+"]已经结束，不能修改！");
		}
		Principal p = ServiceContext.getContext().getPrincipal();
		if(updator == null && p != null) {
			updator = p.getName();
		}
		if(status == Status.FINISHED.value()) {
			this.finishInvestment(invest_id, status, v.getQuantity(), v.getAmount(), null);
			actual_end = new Date();
		} else {
			actual_end = null;
		}
		Assets assets = this.as.findById(assets_id);
		//
		return ModelFactory.create(ActionResult.class, 
				Investment.SURVEY_STATUS, survey_id == null?SurveyStatus.NONE.value: SurveyStatus.CREATED,
				Investment.CURRENCY, currency == null?assets.getCurrency(): currency,
				Investment.NAME, name == null?assets.getName(): name,
				Investment.CODE, code == null?assets.getCode(): code,
				Investment.ACTUAL_END, actual_end,
				
				Investment.UPDATOR, (p == null?null: p.getName()),
				Investment.UPDATE_TIME, new Date());
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	public ActionResult updateAmount(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.PLAN_MONEY, required=false,	desc="计划投入金额") Double plan_money,
			@Param(value=Investment.ACTUAL_MONEY, required=false,	desc="实际投入金额") Double actual_money,
			@Param(value=Investment.TAX, required=false,	desc="税额") Double tax,
			@Param(value=Investment.QUANTITY, required=false,	desc="资产数量") Double quantity,
			@Param(value=Investment.COST, required=false,	desc="成本") Double cost,
			@Param(value=Investment.COST_PRICE, required=false,	desc="成本价") Double cost_price,
			@Param(value=Investment.AMOUNT, required=false,	desc="市值") Double amount,
			@Param(value=Investment.PRICE, required=false,	desc="市价") Double price,
			@Param(value=Investment.REMARKS, required=false,	desc="说明") String remarks,

			@Param(value=Investment.UPDATOR, required=false,	desc="修改人") String updator,
			@Param(value=Investment.UPDATE_TIME, required=false,	desc="修改时间") Date update_time
			
		) throws Exception {
		Investment v = this.findById(invest_id);
		if(v.getStatus() == Status.FINISHED.value()) {
			throw new AppException("0101", v.getName()+"["+v.getCode()+"]已经结束，不能修改！");
		}
		Assets assets = this.as.findById(v.getAssetsId());
		//
		v.setActualMoney(null);
		v.setCost(null);
		v.setTax(null);
		v.setQuantity(null);
		v.setAmount(null);
		if(price == null) price = assets.getPrice();
		v = this.resetMoney(v, assets, TransactionType.BUY.value(), amount, quantity, tax, price);
		v.setCost(cost);
		v.setAmount(amount);
		//
		Principal p = ServiceContext.getContext().getPrincipal();
		return ModelFactory.create(ActionResult.class, 
				
				Investment.ACTUAL_MONEY,v.getActualMoney(),
				Investment.TAX,v.getTax(),
				Investment.QUANTITY,v.getQuantity(),
				Investment.COST,v.getCost(),
				Investment.COST_PRICE,v.getCostPrice(),
				Investment.AMOUNT,v.getAmount(),
				
				Investment.UPDATOR, (p == null?null: p.getName()),
				Investment.UPDATE_TIME, new Date());
	}

	@MethodInfo("修改")
	@Transaction
	public ActionResult updateByTransaction(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,

			@Param(value=InvestmentTransaction.TRANSACTION_TYPE, required=true,	desc="交易类型", enumClass=TransactionType.class) Integer transaction_type,
			@Param(value=InvestmentTransaction.AMOUNT, required=false,	desc="交易金额") Double amount,
			@Param(value=InvestmentTransaction.QUANTITY, required=false,	desc="交易数量") Double quantity,
			@Param(value=InvestmentTransaction.TAX, required=false,	desc="交易税额") Double tax,
			@Param(value=InvestmentTransaction.PRICE, required=true,	desc="交易价格") Double price
			
		) throws Exception {
		Investment v = this.findById(invest_id);
		if(v.getStatus() == Status.FINISHED.value()) {
			throw new AppException("0101", v.getName()+"["+v.getCode()+"]已经结束，不能修改！");
		}
		if(transaction_type == TransactionType.SELL.value() && quantity > v.getQuantity()) {
			throw new AppException("0101", "交易数量大于投资产品数量！");
		}
		Assets a = this.as.findById(v.getAssetsId());
		v = this.resetMoney(v, a, transaction_type, amount, quantity, tax, price);
		if(v.getQuantity() == 0) {
			v.setStatus(Status.FINISHED.value());
		}
		this.updateByTransaction2(invest_id, v.getActualMoney(), v.getTax(), v.getQuantity(), v.getCost(), v.getCostPrice(), 
				v.getAmount(), v.getStatus(), null, null);
		//
		return ModelFactory.create(ActionResult.class, 
				Codes.CODE, Codes.SUCCESS);
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	protected ActionResult updateByTransaction2(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.ACTUAL_MONEY, required=false,	desc="实际投入金额") Double actual_money,
			@Param(value=Investment.TAX, required=false,	desc="税额") Double tax,
			@Param(value=Investment.QUANTITY, required=false,	desc="资产数量") Double quantity,
			@Param(value=Investment.COST, required=false,	desc="成本") Double cost,
			@Param(value=Investment.COST_PRICE, required=false,	desc="成本价") Double cost_price,
			@Param(value=Investment.AMOUNT, required=false,	desc="市值") Double amount,
			@Param(value=Investment.STATUS, required=false,	desc="状态") Integer status,
			@Param(value=Investment.UPDATOR, required=false,	desc="修改人") String updator,
			@Param(value=Investment.UPDATE_TIME, required=false,	desc="修改时间") Date update_time
			
		) throws Exception {
		Investment v = this.findById(invest_id);
		if(v.getStatus() == Status.FINISHED.value()) {
			throw new AppException("0101", v.getName()+"["+v.getCode()+"]已经结束，不能修改！");
		}
		if(status == Status.FINISHED.value()) {
			this.finishInvestment(invest_id, status, quantity, amount, null);
		}
		Principal p = ServiceContext.getContext().getPrincipal();
		return ModelFactory.create(ActionResult.class, 
				Investment.UPDATOR, (p == null?null: p.getName()),
				Investment.UPDATE_TIME, new Date());
	}
	
	@MethodInfo("修改")
	@Transaction
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	protected ActionResult finishInvestment(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态") Integer status,
			@Param(value=Investment.QUANTITY, required=false,	desc="资产数量") Double quantity,
			@Param(value=Investment.AMOUNT, required=false,	desc="市值") Double amount,
			@Param(value=Investment.ACTUAL_END, required=false,	desc="实际结束") Date actual_end
			
		) {
		Investment v = this.findById(invest_id);
		if(v.getStatus() == Status.FINISHED.value()) {
			throw new AppException("0101", v.getName()+"["+v.getCode()+"]已经结束，不能修改！");
		}
		if(quantity != 0) {
			throw new AppException("0101", v.getName()+"["+v.getCode()+"]尚有余量，不能结束！");
		}
		//
		var p = ServiceContext.getContext().getPrincipal();
		var updator = p ==null?null: p.getName();
		//结束所有策略
		this.strategyService.closeAllActivesByInvestId(invest_id, updator, new Date());
		//结束所有交易
		this.transactionService.closeAllActivesByInvestId(invest_id, updator, new Date());
		//取消所有建议
		this.suggestionService.closeAllActivesByInvestId(invest_id, updator, new Date());
		//
		return ModelFactory.create(ActionResult.class,  Investment.ACTUAL_END, new Date());
	}
	
	private Investment resetMoney(Investment v, Assets a,
			@Param(value=InvestmentTransaction.TRANSACTION_TYPE, required=true,	desc="交易类型", enumClass=TransactionType.class) Integer transaction_type,
			
			@Param(value=InvestmentTransaction.AMOUNT, required=false,	desc="交易金额") Double amount,
			@Param(value=InvestmentTransaction.QUANTITY, required=false,	desc="交易数量") Double quantity,
			@Param(value=InvestmentTransaction.TAX, required=false,	desc="交易税额") Double tax,
			@Param(value=InvestmentTransaction.PRICE, required=true,	desc="交易价格") Double price) {

		if(amount == null && quantity == null) {
			throw new AppException("0101", "交易金额和交易数量不能都为空！");
		}
		if(amount == null) {
			amount = quantity * price;
		}
		if(quantity == null) {
			quantity = amount / price;
		}
		if(tax == null) {
			tax = amount * (a.getTaxRate() == null? 0: a.getTaxRate());
		}
		//
		if(v.getActualMoney() == null) v.setActualMoney(0.0);
		if(v.getCost() == null) v.setCost(0.0);
		if(v.getTax() == null) v.setTax(0.0);
		if(v.getQuantity() == null) v.setQuantity(0.0);
		if(v.getAmount() == null) v.setAmount(0.0);
		
		if(transaction_type == TransactionType.BUY.value()) {
			v.setActualMoney(v.getActualMoney() + amount);
			v.setCost(v.getCost() + amount);
			v.setQuantity(v.getQuantity() + quantity);
		} else {
			v.setCost(v.getCost() - amount);
			v.setQuantity(v.getQuantity() - quantity);
		}
		v.setTax(v.getTax() + tax);
		v.setAmount(v.getQuantity() * price);
		if(v.getQuantity() > 0) {
			v.setCostPrice(v.getCost() / v.getQuantity());
		} else {
			v.setCostPrice(0.0);
		}
		//
		return v;
	}

	@MethodInfo("修改")
	@Transaction
	public ActionResult updatePriceByAssetsId(
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.PRICE, required=true,	desc="价格") Double price
		) throws Exception {
		var vs = this.findByAssetsId(assets_id).getRows();
		vs.stream().filter(x -> x.getStatus() != Status.FINISHED.value()).forEach(x -> {
			Double amount = x.getQuantity() * price;
			this.updatePrice(x.getInvestId(), price, amount);
		});
		//
		return ModelFactory.create(ActionResult.class, 
				Codes.CODE, Codes.SUCCESS);
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	protected ActionResult updatePrice(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.PRICE, required=true,	desc="市价") Double price,
			@Param(value=Investment.AMOUNT, required=true,	desc="市值") Double amount
		) {
		return null;
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	public ActionResult updateIncludeStrategies(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.INCLUDE_STRATEGIES, required=false,	desc="包含的策略") String include_strategies
		) {
		if(include_strategies == null) {
			List<Strategy> list = this.strategyService.findByInvestId(invest_id).getRows();
			include_strategies = "";
			for(int i=0; i < list.size(); i++) {
				if(list.get(i).getStatus() != Strategy.Status.PROCESSING.value()) continue;
				if(include_strategies.length() > 0) include_strategies += ",";
				include_strategies += list.get(i).getStrategyType().getCode();
			}
			return ModelFactory.create(ActionResult.class, Investment.INCLUDE_STRATEGIES, include_strategies);
		} else {
			return null;
		}
	}

	@MethodInfo("删除")
	@Transaction
	@DaoRemove(entity=Investment.ENTITY_NAME)
	public ActionResult remove(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id
		) throws Exception {
		this.transactionService.removeByInvestId(invest_id);
		this.strategyService.removeByInvestId(invest_id);
		return null;
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=true, modelClass=Investment.class)
	public QueryResult<Investment> findAll(
			@Param(value=Investment.ACCOUNT_ID, required=false,	desc="投资账户ID") Long account_id,
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, tag="IN") Integer[] status,
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Investment.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null && p != null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, Investment.USER_ID, user_id);
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=true, modelClass=Investment.class, wsql="status < 9")
	public QueryResult<Investment> findAllActives(
			@Param(value=Investment.ACCOUNT_ID, required=false,	desc="投资账户ID") Long account_id,
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, tag="IN") Integer[] status,
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Investment.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null && p != null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, Investment.USER_ID, user_id);
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	public QueryResult<Investment> queryAllActives(
			@Param(value=Investment.ACCOUNT_ID, required=false,	desc="投资账户ID") Long account_id,
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, tag="IN") Integer[] status,
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Investment.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		List<Investment> list = this.findAllActives(account_id, user_id, assets_id, status, survey_status, name, page, rows).getRows();
		List<Investment> result = Utils.newArrayList();
		for(Investment invest: list) {
			if(result.stream().anyMatch(x -> x.getAssetsId() == invest.getAssetsId())) continue;
			List<Investment> children = list.stream().filter(x -> x.getAssetsId() == invest.getAssetsId()).toList();
			if(children.size() == 1) {
				result.add(invest);
			} else {
				result.add(new InvestmentProxy(children));
			}
		}
		return ModelFactory.create(QueryResult.class, 
				Codes.ROWS, result,
				Codes.CODE, Codes.SUCCESS,
				"pageCount", 1,
				"pageNum", 1,
				"pageSize", result.size(),
				"total", result.size());
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索，去掉纯债部分")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=true, modelClass=Investment.class, 
	qsql="select t.* from i_investment t join i_assets a on t.assets_id = a.assets_id and a.type_id not in(52,53) ", wsql="t.status < 9")
	public QueryResult<Investment> findAllActives2(
			@Param(value=Investment.ACCOUNT_ID, required=false,	desc="投资账户ID") Long account_id,
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, tag="IN") Integer[] status,
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Investment.NAME, required=false,	desc="名称", tag="LIKE") String name,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows,
			@Param(value=Codes.SORT, 	required=false, desc="排序字段") String sort,
			@Param(value=Codes.ORDER, 	required=false, desc="排序顺序") String order) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null && p != null) user_id = Long.parseLong(p.getId());
		var sortFields = new HashMap<String, String>();
		sortFields.put("assetsName", 	"name");
		sortFields.put("currency", 	"currency");
		sortFields.put("status", 	"status");
		sortFields.put("quantity", 	"quantity");
		sortFields.put("cost_price", 	"cost_price");
		sortFields.put("cost", 	"cost");

		sortFields.put("amount", 	"amount");
		sortFields.put("max_profit", 	"max_profit");
		sortFields.put("min_profit", 	"min_profit");
		sortFields.put("profit", 	"amount - cost");
		sortFields.put("fell_profit", 	"fell_profit");
		sortFields.put("fell_amount", 	"max_profit - (amount - cost)");
		sortFields.put("fell_rate", "(max_profit - (amount - cost)) / max_profit");
		
		if(sortFields.containsKey(sort)) {
			sort = sortFields.get(sort);
		} else {
			sort = null;
		}
		return ModelFactory.create(QueryResult.class,
				Codes.SORT, sort,
				Investment.USER_ID, user_id);
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=false, modelClass=Investment.class, 
		qsql="select invest_id, name from i_investment t", wsql="status < 9")
	public QueryResult<Investment> findAllActivesForSelections(
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, tag="IN") Integer[] status,
			@Param(value=Investment.NAME, required=false,	desc="名称", tag="LIKE") String name) {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, Investment.USER_ID, user_id);
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=true, modelClass=Investment.class, 
		qsql="select * from v_invest_assets t", csql="select count(0) c from v_invest_assets t", wsql="t.status < 9")
	public QueryResult<Investment> findForMonitor(
			@Param(value=Investment.USER_ID, required=true,	desc="所属用户") Long user_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class, tag="IN") Integer[] status,

			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Assets.TYPE_ID, required=false,	desc="类型ID") Long type_id,
			@Param(value=Assets.MARKET_ID, required=false,	desc="市场ID") Long market_id,
			@Param(value=Assets.BLOCK_ID, required=false,	desc="板块ID") Long block_id,
			
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=false, modelClass=Investment.class)
	public QueryResult<Investment> findByAssetsId(
			@Param(value=Investment.ASSETS_ID, required=true,	desc="投资品种") Long assets_id) {
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=false, modelClass=Investment.class)
	public QueryResult<Investment> findByUserId(
			@Param(value=Investment.USER_ID, required=true,	desc="所属用户") Long user_id) {
		return null;
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=true, modelClass=Investment.class)
	public QueryResult<Investment> findAll2(
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.SURVEY_ID, required=false,	desc="调查ID") Long survey_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class) Integer status,
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) throws Exception {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, Investment.USER_ID, Long.parseLong(p.getId()));
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("搜索")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=true, modelClass=Investment.class, wsql="EXISTS(SELECT 1 FROM i_strategy is2 WHERE t.invest_id=is2.invest_id)")
	public QueryResult<Investment> findAll2WithStrategy(
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id,
			@Param(value=Investment.ASSETS_ID, required=false,	desc="投资品种") Long assets_id,
			@Param(value=Investment.SURVEY_ID, required=false,	desc="调查ID") Long survey_id,
			@Param(value=Investment.STATUS, required=false,	desc="状态", enumClass=Status.class) Integer status,
			@Param(value=Investment.SURVEY_STATUS, required=false,	desc="问卷状态", enumClass=SurveyStatus.class) Integer survey_status,
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) throws Exception {
		Principal p = ServiceContext.getContext().getPrincipal();
		if(user_id == null) user_id = Long.parseLong(p.getId());
		return ModelFactory.create(QueryResult.class, Investment.USER_ID, Long.parseLong(p.getId()));
	}

	@MethodInfo("查询")
	@DaoQuery(entity=Investment.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public Investment findById(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id
		) {
		return null;
	}
	
	//
	@MethodInfo("搜索投资项统计信息")
	@DaoQuery(entity=Investment.ENTITY_NAME, pageable=false, modelClass=Investment.class, 
		qsql="select * from v_invest_stat t ")
	protected QueryResult<Investment> findInvestStat(
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id) {
		return null;
	}
	
	@MethodInfo("修改")
	@DaoUpdate(entity=Investment.ENTITY_NAME)
	protected ActionResult updateStatByInvestId(
			@Param(value=Investment.INVEST_ID, required=true,	desc="ID") Long invest_id,
			@Param(value=Investment.MAX_PROFIT, required=false,	desc="最大利润") Double max_profit,
			@Param(value=Investment.MIN_PROFIT, required=false,	desc="最小利润") Double min_profit,
			@Param(value=Investment.FELL_PROFIT, required=false,	desc="回落最小利润") Double fell_profit,
			@Param(value=Investment.MAX_PRICE, required=false,	desc="最高价格") Double max_price,
			@Param(value=Investment.MIN_PRICE, required=false,	desc="最低价格") Double min_price
		) {
		return null;
	}
	
	@MethodInfo("修改")
	@Transaction
	public ActionResult updateStatByUserId(
			@Param(value=Investment.USER_ID, required=false,	desc="所属用户") Long user_id) {
		var list = this.findInvestStat(user_id).getRows();
		list.stream().forEach(x -> {
			var invest = this.findById(x.getInvestId());
			var price = this.aps.findTopPriceByAssetsId(invest.getAssetsId(), invest.getCreateTime(), new Date());
			this.updateStatByInvestId(x.getInvestId(), x.getMaxProfit(), x.getMinProfit(), x.getFellProfit(),
					price.getMaxPrice(), price.getMinPrice());
		});
		return ModelFactory.create(ActionResult.class,  Investment.ACTUAL_END, new Date());
	}

}